/*
 * This file is a part of the RMI Plugin for Eclipse tutorials.
 * Copyright (C) 2002-7 Genady Beryozkin
 * 
 * You are free to modify this file, as long as you leave
 * the following copyright:
 * 
 * This file is based on the Remote File System example of
 * the RMI Plug-in for Eclipse. The original code is 
 * Copyright (C) 2002-7 Genady Beryozkin
 */

package rmi.filesystem.server;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.regex.Pattern;

import rmi.filesystem.common.IRemoteFile;
import rmi.filesystem.common.IRemoteFilenameFilter;
import rmi.filesystem.common.IRemoteInputStream;
import rmi.filesystem.common.IRemoteOutputStream;


/**
 * This class implements the {@link IRemoteFile} interface for
 * the local file system. The implementation extends the standard 
 * {@link File} class. Some methods already appear in the {@link File} 
 * class with the same signature as required by the interface and 
 * therefore you don't see their implementation here.
 * 
 * As you can see this class does not extend {@link UnicastRemoteObject},
 * which means we have to manually export the remote implementations
 * using the {@link UnicastRemoteObject#exportObject(java.rmi.Remote)}
 * method. 
 * 
 * This implementation tries to be as efficient as it can be, but
 * you should remember that the whole design is not very efficient itself.
 * 
 * The interesting methods in terms of two-way communications are the methods
 * that filter the file system. See their docs and the docs in the interface
 * for more information. 
 * 
 * @author Genady Beryozkin, rmi-info@genady.net
 */
public class RemoteFileImpl extends File implements IRemoteFile {

	private static final long serialVersionUID = 7626055290618282111L;
	
	private String oldAbsolutePath;
	private long lastArchived;

	/**
	 * Create a new remote file object with a given path. Used only
	 * by {@link RemoteFileSystemImpl#getRoots()}.
	 */
	RemoteFileImpl(String pathname) throws RemoteException {
		super(pathname);
		UnicastRemoteObject.exportObject(this);
//		try {
//			System.out.println("Nowy plik na serwerze " + this.createNewFile());
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}

	/**
	 * Create a new remote file object that is a child of this directory.
	 */
	public RemoteFileImpl(RemoteFileImpl parent, String child) throws RemoteException {
		super(parent, child);
		UnicastRemoteObject.exportObject(this);
	}
	
	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#getRemoteParentFile()
	 */
	public RemoteFileImpl getRemoteParentFile() throws RemoteException {
		return new RemoteFileImpl(super.getParent());
	}

	
	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#getRemoteAbsoluteFile()
	 */
	public RemoteFileImpl getRemoteAbsoluteFile() throws RemoteException {
		return new RemoteFileImpl(super.getAbsolutePath());
	}
	
	/* 
	 * The super implementation can throw an IOException, but we must wrap it
	 * with a RemoteException.
	 * 
	 * (non-Javadoc)
	 * @see java.io.File#getCanonicalPath()
	 */
	@Override
	public String getCanonicalPath() throws RemoteException {
		try {
			return super.getCanonicalPath();
		} catch (IOException e) {
			throw new RemoteException("Error getting the canonical path", e);
		}
	}
	
	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#getChild(java.lang.String)
	 */
	public IRemoteFile getChild(String name) throws RemoteException {
		return new RemoteFileImpl(this, name);
	}
	
	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#listRemoteFiles()
	 */
	public IRemoteFile[] listRemoteFiles() throws RemoteException {
		File[] children = super.listFiles();
		IRemoteFile[] remoteChildren = new IRemoteFile[children.length];
		for (int i = 0; i < children.length; i++) {
			remoteChildren[i] = new RemoteFileImpl(this, children[i].getName());
		}
		return remoteChildren;
	}
	
	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#listByFilter(demo.rmi.filesystem.common.IRemoteFilenameFilter)
	 */
	public IRemoteFile[] listByFilter(IRemoteFilenameFilter filter) throws RemoteException {
		ArrayList<IRemoteFile> files = new ArrayList<IRemoteFile>();
		File[] children = super.listFiles();
		for (File file : children) {
			// the following is a remote callback.
			if (filter.accept(this, file.getName())) {
				files.add(new RemoteFileImpl(this, file.getName()));
			}
		}
		return files.toArray(new IRemoteFile[]{});
	}

	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#listRemoteDirectories()
	 */
	public IRemoteFile[] listRemoteDirectories() throws RemoteException {
		File[] dirs = super.listFiles(new FileFilter() {
			public boolean accept(File pathname) {
				return pathname.isDirectory();
			}
		});
		IRemoteFile[] remoteDirs = new IRemoteFile[dirs.length];
		for (int i= 0; i < dirs.length; i++) {
			remoteDirs[i] = new RemoteFileImpl(this, dirs[i].getName());
		}
		return remoteDirs;
	}

	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#listByRegex(java.lang.String, boolean)
	 */
	public IRemoteFile[] listByRegex(String regex, final boolean dirsOnly) throws RemoteException {
		final Pattern pattern = Pattern.compile(regex);
		File[] selectedFiles = super.listFiles(new FileFilter() {
			public boolean accept(File file) {
				return (!dirsOnly || file.isDirectory()) && pattern.matcher(file.getName()).matches();
			}
		});
		IRemoteFile[] selectedRemoteFiles = new IRemoteFile[selectedFiles.length];
		for (int i= 0; i < selectedFiles.length; i++) {
			selectedRemoteFiles[i] = new RemoteFileImpl(this, selectedFiles[i].getName());
		}
		return selectedRemoteFiles;
	}

	public IRemoteInputStream getInputStream() throws RemoteException {
		try{
			return new RemoteInputStreamImpl(this);
		}catch(FileNotFoundException e){
			throw new RemoteException("RemoteInputStreamImpl", e);
		}

	}

	public IRemoteOutputStream getOutputStream() throws RemoteException {
		try{
			return new RemoteOutputStreamImpl(this);
		}catch(FileNotFoundException e){
			throw new RemoteException("RemoteOutputStreamImpl", e);
		}
	}
	
	public String getOldAbsolutePath() throws RemoteException {
		
			
			return oldAbsolutePath;
	}
	
	public void setOldAbsolutePath(String absolutePath) throws RemoteException{
		
		oldAbsolutePath = absolutePath;
	}

	public long getLastArchived() throws RemoteException {
		
		return lastArchived;
	}
	
	public void setLastArchived(long lastarchived) throws RemoteException{
		
		lastArchived = lastarchived;
	}
	


	/* (non-Javadoc)
	 * @see demo.rmi.filesystem.common.IRemoteFile#getInputStream()
	 */
	
}
